/*!
 * \file build_sparse_constraints_visitor.h
 *
 * \brief Declarations of the BuildSparseConstraintsVisitor that traverses the
 *        AST
 *
 * \date Started: 6/8/2010
 * \date Last Modified: 6/8/2010
 * \authors Alan LaMielle
 * \authors Nicholas Jeanette
 *
 * Copyright (c) 2010, Colorado State University <br>
 * All rights reserved. <br>
 * See ../../COPYING for details. <br>
 */

#ifndef BUILD_SPARSE_CONSTRAINTS_VISITOR_H_
#define BUILD_SPARSE_CONSTRAINTS_VISITOR_H_

#include <iegenlib/iegenlib.h>

#include <map>
#include <list>
#include <set>

namespace iegenlib{

/*!
 * \class BuildSparseConstraints
 * \brief Visitor class that is used to build the SparseConstraints class
 *
 * This class uses the DepthFirstVisitorAdapter to visit the AST so it
 * can build the sparse constraints
 */
class BuildSparseConstraints: public DepthFirstVisitorAdapter{
public:

   /*!
   * Build Sparse Constraints Constructor
   *
   * The constructor for the BuildSparseConstraints
   * @param a pointer to the Symbol Table that will be used.
   */
   BuildSparseConstraints(SymbolTable*, set<SREquality> equals, list<TupleType> tups);

//   void UnionOut(Union* node);
  /*!
   * Used for general tasks to be done going into every visited node
   * @param node node to do tasks on
   */
   inline void defaultIn(Node* node){}

   /*!
   * Used for general tasks to be done going out of every visited node
   * @param node node to do tasks on
   */
   inline void defaultOut(Node* node){}


   /*!
   * This is leaving the root node in this function all of the tree has been
   * traversed and everything had been constructed and filled. This calls
   * buildSpConstraints to actually construct the constraints
   * @param pointer to the PresSet node in the ast (this is the root node)
   */
//   void PresSetOut(PresSet* node);

   /*!
   * This is leaving the root node in this function all of the tree has been
   * traversed and everything had been constructed and filled. This calls
   * buildSpConstraints to actually construct the constraints
   * @param pointer to the PresSet node in the ast (this is the root node)
   */
//   void PresRelationOut(PresRelation* node);

   /*!
   * method called by the VarExpCase method for the VarExp node
   * used to insert the node into the map
   * @param node node that calls the case method
   */
   void VarExpOut(VarExp* node);

   /*!
   * method called by the NormExpCase method for the NormExp node
   * used to insert the node into the map and add all ExpVec together
   * @param node node that calls the case method
   */
   void NormExpOut(NormExp* node);

   /*!
   * method called by the FuncExpCase method for the FuncExp node
   * used to insert the node into the map
   * @param node node that calls the case method
   */
   void FuncExpOut(FuncExp* node);

   std::string toString();

   /*!
   * A function called by the FuncExpOut used to create the toString for the
   * function name. This name is the node name with the concatenation of all
   * the expression vectors toString that are associated with said function.
   * @param a pointer to the function expression node we are getting the name of
   * @return a string representation of the function node name
   */
   std::string funcExpString(FuncExp* node);

   /*!
   * used to build the SRConjunction grabs the two sets of SREqualities and
   * SRInequalities, EqConjSet and IeqConjSet respectively. These sets are then
   * used to create a SRConjunction. The SRCOnjunction is then placed in a set
   * ConjunctSet
   */
   void ConjunctionOut(Conjunction* node);

   /*!
   * used to build the SREquality. creates a SREquality from the expVec of
   * the child node (this child is a normExp that has already be created and
   * mapped to the mNodeToExpVecs). This new SREquality is placed into the
   * EqConjSet
   */
   void EqualityOut(Equality* node);

   /*!
   * used to build the SRInequality. creates a SRInequality from the expVec of
   * the child node (this child is a normExp that has already be created and
   * mapped to the mNodeToExpVecs). This new SRInequality is placed into the
   * IeqConjSet
   */
   void InequalityOut(Inequality* node);

   /*!
   * used to get the SRConjuctions created when the buildsparseconstraint pass is
   * done.
   * &return the set of SRConjunctions made
   */
   SRConjunction getConjunction();

   /*!
   * A function that creates equalities between two duplicate tuple vars. This
   * creates two expression vectors with coeffs of 1 to the original and -1
   * to the new (unique name). It then creates the equality and adds to the set
   */

    /*!
   * This is leaving the root node in this function all of the tree has been
   * traversed and all lists/sets have been constructed and filled. All that is
   * needed is creation of unique names and function calls the method to do so.
   * @param pointer to the PresSet node in the ast (this is the root node)
   */
   void PresSetIn(PresSet* node);

   /*!
   * This is leaving the root node in this function all of the tree has been
   * traversed and all lists/sets have been constructed and filled. All that is
   * needed is creation of unique names and function calls the method to do so.
   * @param pointer to the PresRelation node in the ast (this is the root node)
   */
   void PresRelationIn(PresRelation* node);


private:
   /// a map that maps pointers of nodes to ExpVecs
   map<const Node*,ExpVec> mNodeToExpVec;

   /// a map that maps poiter of constraint nodes to the nodes childs ExpVec
   map<Constraint*,ExpVec> mIeqConstraintToExpVec;

   /// a map that maps poiter of constraint nodes to the nodes childs ExpVec
   map<Constraint*,ExpVec> mEqConstraintToExpVec;

   ///this is a pointer to the symbol table
   SymbolTable* ST;

   /// a set of SREqualities used to make a conjunction
   set<SREquality> EqConjSet;

   /// a set of SRInequalities used to make a conjunction
   set<SRInequality> IeqConjSet;

   /// a set of all SRConjunctions that have been created
   SRConjunction *Conjunct;

   list<TupleType> STEList;

   SparseConstraints* mSpConstraint;

};

}//end namespace iegenlib

#endif /* BUILD_SPARSE_CONSTRAINTS_VISITOR_H_ */
